package com.project_doctor.service.impl;

import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.UUID;

@Service
/**
 * 二维码生成服务类
 * 负责处理签约信息二维码的生成和存储
 */
public class QRCodeService {
    // ==================== 配置参数注入 ====================

    @Value("${qrcode.upload.path}")
    private String qrCodePath;

    @Value("${qrcode.server.domain}")
    private String serverDomain;

    @Value("${qrcode.image.width:300}")
    private int imageWidth;

    @Value("${qrcode.image.height:300}")
    private int imageHeight;

    @Value("${qrcode.image.format:PNG}")
    private String imageFormat;

    // JSON处理工具
    private final ObjectMapper objectMapper = new ObjectMapper();

    // 时间格式化工具
    private final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    // ==================== 主要业务方法 ====================
    /**
     * 生成签约信息二维码（在线生成，返回URL）
     * @param contractId 签约ID
     * @param contractData 签约详细信息
     * @return 在线二维码的访问URL
     */
    public String generateContractQRCode(String contractId, Map<String, Object> contractData) throws IOException {

        // 1. 数据验证
        validateInputData(contractId, contractData);

        // 2. 生成签约信息图片并保存到本地
        String imageFileName = generateAndSaveContractImage(contractId, contractData);

        // 3. 构建图片访问URL（使用控制器接口而不是静态资源）
        String imageUrl = String.format("%s/qrcode/image/%s",
                serverDomain.replaceAll("/$", ""), imageFileName);

        // 4. 通过第三方API生成在线二维码，返回URL
        return generateOnlineQRCode(imageUrl);
    }

    // ==================== 核心实现方法 ====================

    /**
     * 生成并保存签约信息图片到本地
     */
    private String generateAndSaveContractImage(String contractId, Map<String, Object> contractData) throws IOException {
        try {
            // 1. 创建图片
            BufferedImage image = createContractInfoImage(contractId, contractData);

            // 2. 生成文件名
            String imageFileName = generateImageFileName(contractId);

            // 3. 保存到本地
            saveImageToFile(image, imageFileName);

            return imageFileName;

        } catch (Exception e) {
            throw new IOException("生成签约图片失败: " + e.getMessage(), e);
        }
    }

    /**
     * 通过第三方API生成在线二维码
     */
    private String generateOnlineQRCode(String content) throws IOException {
        try {
            // 构建第三方API请求URL
            String apiUrl = String.format(
                    "https://api.qrserver.com/v1/create-qr-code/?size=%dx%d&data=%s&format=PNG",
                    imageWidth, imageHeight, java.net.URLEncoder.encode(content, "UTF-8"));

            return apiUrl; // 直接返回第三方API的URL

        } catch (Exception e) {
            throw new IOException("生成在线二维码失败: " + e.getMessage(), e);
        }
    }

    /**
     * 创建签约信息图片内容
     */
    private BufferedImage createContractInfoImage(String contractId, Map<String, Object> contractData) {

        int width = 450;
        int height = 520;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = image.createGraphics();

        // 基础设置
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, width, height);

        // 边框
        g2d.setColor(new Color(200, 200, 200));
        g2d.drawRect(10, 10, width - 20, height - 20);

        // 标题
        g2d.setColor(Color.BLACK);
        g2d.setFont(new Font("SimSun", Font.BOLD, 18));
        drawCenteredText(g2d, "家庭医生签约信息", width, 40);

        // 分割线
        g2d.drawLine(20, 55, width - 20, 55);

        // 内容
        g2d.setFont(new Font("SimSun", Font.PLAIN, 14));
        int y = 80;
        int lineHeight = 20;

        g2d.drawString("签约编号: " + contractId, 25, y); y += lineHeight;
        g2d.drawString("居民姓名: " + getStringValue(contractData, "name"), 25, y); y += lineHeight;
        g2d.drawString("性别: " + formatGender(contractData.get("gender")), 25, y); y += lineHeight;
        g2d.drawString("身份证号: " + getStringValue(contractData, "idCard"), 25, y); y += lineHeight;
        g2d.drawString("联系电话: " + getStringValue(contractData, "phone"), 25, y); y += lineHeight;
        g2d.drawString("现居地址: " + truncateString(getStringValue(contractData, "address"), 20), 25, y); y += lineHeight;
        g2d.drawString("签约医生: " + getStringValue(contractData, "doctor"), 25, y); y += lineHeight;
        g2d.drawString("签约机构: " + getStringValue(contractData, "inst"), 25, y); y += lineHeight;
        g2d.drawString("医生团队: " + getStringValue(contractData, "team"), 25, y); y += lineHeight;
        g2d.drawString("签约类型: " + getStringValue(contractData, "type"), 25, y); y += lineHeight;
        g2d.drawString("服务包: " + getStringValue(contractData, "packageId"), 25, y); y += lineHeight;
        g2d.drawString("签约周期: " + getStringValue(contractData, "signCycle"), 25, y); y += lineHeight;
        g2d.drawString("服务费用: ￥" + getStringValue(contractData, "fee"), 25, y); y += lineHeight;
        g2d.drawString("签约状态: " + getStringValue(contractData, "status"), 25, y); y += lineHeight;
        g2d.drawString("居民标签: " + getStringValue(contractData, "tag"), 25, y); y += lineHeight;
        g2d.drawString("申请时间: " + formatDateTime(contractData.get("applyTime")), 25, y); y += lineHeight;
        g2d.drawString("生效日期: " + formatDateTime(contractData.get("effectiveDate")), 25, y); y += lineHeight;
        g2d.drawString("到期日期: " + formatDateTime(contractData.get("expireDate")), 25, y); y += lineHeight;
        g2d.drawString("签约备注: " + getStringValue(contractData, "remark"), 25, y);

        // 时间戳
        g2d.setColor(Color.GRAY);
        g2d.setFont(new Font("SimSun", Font.PLAIN, 10));
        drawCenteredText(g2d, "生成时间: " + LocalDateTime.now().format(timeFormatter), width, height - 20);

        g2d.dispose();

        return image;
    }

    /**
     * 保存图片到本地文件
     */
    private void saveImageToFile(BufferedImage image, String fileName) throws IOException {
        // 确保目录存在
        Path uploadPath = Paths.get(qrCodePath);
        if (!Files.exists(uploadPath)) {
            Files.createDirectories(uploadPath);
        }

        // 保存图片
        Path imagePath = uploadPath.resolve(fileName);
        javax.imageio.ImageIO.write(image, imageFormat, imagePath.toFile());

        System.out.println("签约图片已生成: " + fileName);
    }

    /**
     * 生成图片文件名
     */
    private String generateImageFileName(String contractId) {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
        String randomSuffix = UUID.randomUUID().toString().substring(0, 6);
        return String.format("contract_%s_%s_%s.%s", contractId, timestamp, randomSuffix, imageFormat.toLowerCase());
    }

    // ==================== 工具方法 ====================

    /**
     * 绘制居中文本
     */
    private void drawCenteredText(Graphics2D g2d, String text, int width, int y) {
        FontMetrics fm = g2d.getFontMetrics();
        int textWidth = fm.stringWidth(text);
        int x = (width - textWidth) / 2;
        g2d.drawString(text, x, y);
    }

    /**
     * 安全获取字符串值
     */
    private String getStringValue(Map<String, Object> data, String key) {
        Object value = data.get(key);
        return value != null ? value.toString() : "未知";
    }

    /**
     * 格式化性别显示
     */
    private String formatGender(Object gender) {
        if (gender == null) return "未知";
        try {
            int genderValue = Integer.parseInt(gender.toString());
            return genderValue == 0 ? "女" : "男";
        } catch (NumberFormatException e) {
            return gender.toString();
        }
    }

    /**
     * 格式化日期时间显示
     */
    private String formatDateTime(Object dateTime) {
        if (dateTime == null) return "未知";
        String dateStr = dateTime.toString();

        // 处理ISO格式日期 "2025-06-06T10:35:31.000+08:00"
        if (dateStr.contains("T")) {
            try {
                return dateStr.substring(0, 10); // 只显示日期部分 "2025-06-06"
            } catch (Exception e) {
                return dateStr;
            }
        }

        return dateStr;
    }

    /**
     * 截断过长的字符串
     */
    private String truncateString(String str, int maxLength) {
        if (str == null || str.length() <= maxLength) {
            return str;
        }
        return str.substring(0, maxLength) + "...";
    }

    /**
     * 输入数据验证
     */
    private void validateInputData(String contractId, Map<String, Object> contractData) {
        if (contractId == null || contractId.trim().isEmpty()) {
            throw new IllegalArgumentException("签约ID不能为空");
        }
        if (contractData == null || contractData.isEmpty()) {
            throw new IllegalArgumentException("签约数据不能为空");
        }
        if (getStringValue(contractData, "name").equals("未知")) {
            throw new IllegalArgumentException("居民姓名不能为空");
        }
    }
}
